package com.jy.rhin.zhibiao.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jy.rhin.infra.repo.zhibiao.mapper.PingTaiDYCSMapper;
import com.jy.rhin.infra.repo.zhibiao.assembler.PingTaiDYCSAssembler;
import com.jy.rhin.zhibiao.model.dto.PingTaiDYCSDto;
import com.jy.rhin.zhibiao.model.po.PingTaiDYCSPo;
import com.jy.rhin.zhibiao.model.po.ZhiBiaoPo;
import com.jy.rhin.zhibiao.service.PingTaiDYCSService;
import com.jy.rhin.zhibiao.service.ZhiBiaoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.Year;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yuyue
 * @date 2024/3/22
 */
@Slf4j
@Service
public class PingTaiDYCSServiceImpl extends ServiceImpl<PingTaiDYCSMapper, PingTaiDYCSPo> implements PingTaiDYCSService {

    private static final String HULIANHUTONG_KEY = "huLianHTRZ::%s::%s";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ZhiBiaoService zhiBiaoService;

    @Override
    public Page<PingTaiDYCSDto> getPage(Integer shiJianWD, String startDate, String endDate, String zhiBiaoLX,
                                        String zhiBiaoDM, Integer pageNo, Integer pageSize) {
        LambdaQueryWrapper<PingTaiDYCSPo> lambdaQueryWrapper = Wrappers.<PingTaiDYCSPo>lambdaQuery()
//                .eq(StrUtil.isNotBlank(zhiBiaoLX), PingTaiDYCSPo::getZhiBiaoLX, zhiBiaoLX)
                .eq(StrUtil.isNotBlank(zhiBiaoDM), PingTaiDYCSPo::getZhiBiaoDM, zhiBiaoDM)
                .ge(StrUtil.isNotBlank(startDate), PingTaiDYCSPo::getTongJiRQ, startDate)
                .le(StrUtil.isNotBlank(endDate), PingTaiDYCSPo::getTongJiRQ, endDate)
                .orderByDesc(PingTaiDYCSPo::getDiaoYongCS);
        if (StrUtil.isNotBlank(zhiBiaoLX)) {
            List<ZhiBiaoPo> list = zhiBiaoService.list(Wrappers.<ZhiBiaoPo>lambdaQuery()
                    .select(ZhiBiaoPo::getZhiBiaoDM)
                    .eq(ZhiBiaoPo::getShangJiId, zhiBiaoLX));
            if (list.isEmpty()) {
                return new Page<>();
            }
            lambdaQueryWrapper.in(PingTaiDYCSPo::getZhiBiaoDM, list.stream()
                    .map(ZhiBiaoPo::getZhiBiaoDM).collect(Collectors.toList()));
        }

        if (Integer.valueOf(3).equals(shiJianWD)) {
            Page<PingTaiDYCSPo> page = this.page(new Page<>(pageNo, pageSize), lambdaQueryWrapper);
            return PingTaiDYCSAssembler.poPageToDtoPage(page);
        } else {
            List<PingTaiDYCSPo> list = this.list(lambdaQueryWrapper);
            if (list.isEmpty()) {
                return new Page<>(pageNo, pageSize);
            }
            return yearOrMonthGet(list, shiJianWD, pageNo, pageSize);
        }
    }

    @Override
    public void tongJiDYCS(String date) {
        List<ZhiBiaoPo> list = zhiBiaoService.list();
        List<PingTaiDYCSPo> pingTaiDYCSPos = new ArrayList<>();
        LocalDate localDate = LocalDate.parse(date);
        for (ZhiBiaoPo zhiBiaoPo : list) {
            String huLianHTKey = String.format(HULIANHUTONG_KEY, date, zhiBiaoPo.getZhiBiaoDM());
            Integer sum = (Integer) redisTemplate.opsForValue().get(huLianHTKey);
            if (sum == null) {
                log.info("{}指标无数据", zhiBiaoPo.getZhiBiaoDM());
                continue;
            }
            PingTaiDYCSPo pingTaiDYCSPo = new PingTaiDYCSPo();
            pingTaiDYCSPo.setZhiBiaoMC(zhiBiaoPo.getZhiBiaoMC());
            pingTaiDYCSPo.setZhiBiaoDM(zhiBiaoPo.getZhiBiaoDM());
            pingTaiDYCSPo.setTongJiRQ(localDate);
            pingTaiDYCSPo.setDiaoYongCS(sum);
            pingTaiDYCSPos.add(pingTaiDYCSPo);
        }
        this.saveBatch(pingTaiDYCSPos);
    }

    /**
     * 时间维度为年或月的数据获取
     */
    private Page<PingTaiDYCSDto> yearOrMonthGet(List<PingTaiDYCSPo> list, Integer shiJianWD, Integer pageNo, Integer pageSize) {
        Page<PingTaiDYCSDto> resPage = new Page<>(pageNo, pageSize);
        LocalDate earliestDate = list.stream()
                .map(PingTaiDYCSPo::getTongJiRQ)
                .min(LocalDate::compareTo)
                .orElse(null);

        LocalDate latestDate = list.stream()
                .map(PingTaiDYCSPo::getTongJiRQ)
                .max(LocalDate::compareTo)
                .orElse(null);
        List<PingTaiDYCSDto> pingTaiDYCSDTOS = new ArrayList<>();
        if (Integer.valueOf(2).equals(shiJianWD)) {
            YearMonth start = YearMonth.from(earliestDate);
            YearMonth end = YearMonth.from(latestDate);
            for (YearMonth ym = start; !ym.isAfter(end); ym = ym.plusMonths(1)) {
                LocalDate firstDay = ym.atDay(1);
                LocalDate lastDay = ym.atEndOfMonth();
                pingTaiDYCSDTOS.addAll(splitData(firstDay, lastDay, list));
            }
        } else {
            Year startYear = Year.from(earliestDate);
            Year endYear = Year.from(latestDate);

            for (Year year = startYear; !year.isAfter(endYear); year = year.plusYears(1)) {
                LocalDate firstDayOfYear = year.atDay(1);
                LocalDate lastDayOfYear = year.atDay(year.length());
                pingTaiDYCSDTOS.addAll(splitData(firstDayOfYear, lastDayOfYear, list));
            }
        }
        List<PingTaiDYCSDto> sortedList = pingTaiDYCSDTOS.stream()
                .sorted(Comparator.comparing(PingTaiDYCSDto::getDiaoYongCS).reversed())
                .collect(Collectors.toList());

        // 分页处理
        int totalSize = sortedList.size();
        int fromIndex = (pageNo - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, totalSize);
        List<PingTaiDYCSDto> pageResult = sortedList.subList(fromIndex, toIndex);
        resPage.setRecords(pageResult);
        resPage.setTotal(pingTaiDYCSDTOS.size());

        return resPage;
    }

    private List<PingTaiDYCSDto> splitData(LocalDate firstDay, LocalDate lastDay, List<PingTaiDYCSPo> list) {
        List<PingTaiDYCSDto> pingTaiDYCSDTOS = new ArrayList<>();
        Map<String, List<PingTaiDYCSPo>> listMap = list.stream()
                .filter(po -> po.getTongJiRQ().isAfter(firstDay) && po.getTongJiRQ().isBefore(lastDay))
                .collect(Collectors.groupingBy(PingTaiDYCSPo::getZhiBiaoDM));
        for (List<PingTaiDYCSPo> value : listMap.values()) {
            PingTaiDYCSPo pingTaiDYCSPo = value.get(0);
            PingTaiDYCSDto pingTaiDYCSDTO = new PingTaiDYCSDto();
            pingTaiDYCSDTO.setTongJiRQ(lastDay);
            pingTaiDYCSDTO.setZhiBiaoMC(pingTaiDYCSPo.getZhiBiaoMC());
            pingTaiDYCSDTO.setZhiBiaoDM(pingTaiDYCSPo.getZhiBiaoDM());
            pingTaiDYCSDTO.setDiaoYongCS(value.stream()
                    .mapToInt(PingTaiDYCSPo::getDiaoYongCS)
                    .sum());
            pingTaiDYCSDTOS.add(pingTaiDYCSDTO);
        }
        return pingTaiDYCSDTOS;
    }
}
